﻿using System;
using System.Collections.Generic;
using DynConDevCorp.OpenArch.SmartData.Core.Metadata;
using DynConDevCorp.OpenArch.SmartData.Interfaces;
using DynConDevCorp.OpenArch.SmartData.Interfaces.MetaData;

namespace DynConDevCorp.OpenArch.SmartData.Core
{
    public class SmartEntityTransform
    {

        public TTarget Transform<TSource, TTarget>(TSource src)
            where TSource : ISmartEntity
            where TTarget : ISmartEntity
        {
             List<ISmartMetaAutoField> commonFields = GetMappedFields(typeof(TSource), typeof(TTarget));
            SmartFactory.GlobalInstance.CreateEntityInstance<TTarget>(src.EntityID);
            TTarget target = SmartFactory.GlobalInstance.CreateEntityInstance<TTarget>(src.EntityID); 
            foreach (ISmartMetaAutoField fld in commonFields)
            {
                target[fld.FieldName].RawValue = src[fld.FieldName].RawValue;
            }
            return target;
        }

        private List<ISmartMetaAutoField> GetMappedFields(Type srcType, Type tgtType)
        {
            List<ISmartMetaAutoField> srcFields = SmartMetaDataStore.GlobalInstance.GetMetaEntity(srcType).GetAutoFields();
            List<ISmartMetaAutoField> tgtFields = SmartMetaDataStore.GlobalInstance.GetMetaEntity(tgtType).GetAutoFields();
            List<ISmartMetaAutoField> commonFields = new List<ISmartMetaAutoField>();
            foreach (ISmartMetaAutoField srcField in srcFields)
            {
                foreach (ISmartMetaAutoField tgtField in tgtFields)
                {
                    if (srcField.FieldName == tgtField.FieldName)
                    {
                        commonFields.Add(tgtField);
                    }
                }
            }
            return commonFields;
        }

        public ISmartEntityCollection<TTargetEntity> Transform<TSource, TTargetEntity>(ISmartEntityCollection<TSource> srcCollection)
            where TSource : ISmartEntity
            where TTargetEntity : ISmartEntity, new()
        {
            return Transform<TSource, SmartEntityCollection<TTargetEntity>, TTargetEntity>(srcCollection);
        }

        public TTargetCollection Transform<TSource, TTargetCollection, TTargetEntity>(ISmartEntityCollection<TSource> srcCollection)
            where TSource : ISmartEntity
            where TTargetEntity : ISmartEntity
            where TTargetCollection : ISmartEntityCollection<TTargetEntity>, new()
        {
            TTargetCollection retVal = new TTargetCollection();
            List<ISmartMetaAutoField> commonFields = GetMappedFields(typeof(TSource), typeof(TTargetEntity));
            foreach (TSource srcEntity in srcCollection)
            {
                TTargetEntity tgtEntity = (TTargetEntity) Activator.CreateInstance(typeof (TTargetEntity), new object[] {srcEntity.EntityID});
                foreach (ISmartMetaAutoField fld in commonFields)
                {
                    tgtEntity[fld.FieldName].RawValue = srcEntity[fld.FieldName].RawValue;
                }
                retVal.Add(tgtEntity);
            }
            return retVal;
        }
    }
}